#version 120

uniform sampler2D backfacetexture;
uniform sampler3D volumetexture;

uniform sampler1D tranf;

varying vec4 vposition;
uniform vec4 lightposition;

uniform float stepsize;




float rand(vec2 co)
{        
	return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) / 200;        
} 




void main()
{
	vec2 texposition = ((vposition.xy/vposition.w) + 1.0)/2.0;
	vec4 start = gl_TexCoord[0];
	vec3 dir;
	vec4 backposition1 = texture2D(backfacetexture, texposition);
	dir.x = backposition1.x - start.x;
	dir.y = backposition1.y - start.y;
	dir.z = backposition1.z - start.z;
	float len = length(dir);
	vec3 norm_dir = normalize(dir);
	float iso_value = 0.2;

   float delta = stepsize;
   vec3 delta_dir = norm_dir * delta;
   float delta_dir_len = length(delta_dir);
   vec3 vec = start.xyz;
   vec4 col_acc = vec4(0,0,0,0);
   float alpha_acc = 0;
   float length_acc = 0;
   vec4 color_sample;
   float alpha_sample;
  
  vec4 colorvalue; 
  for(int i = 0; i < 400; i++)
    {
      color_sample = texture3D(volumetexture,vec);
	  if(color_sample.x > iso_value)
	  {
		  break;
	  }
	  vec += delta_dir;
      length_acc += delta_dir_len;
	  if(length_acc >= len)
		  discard;
  }

  vec3 delta_e = delta_dir/2;
  vec -= delta_e;
  length_acc -= length(delta_e);
  		  
  for(int j=0; j<6; j++)
  {
      color_sample = texture3D(volumetexture,vec);
	  if(color_sample.x < iso_value)
	  {
		  vec += delta_e;
		  length_acc += length(delta_e);
	  }
	  else
	  {
		  vec -= delta_e;
		  length_acc -= length(delta_e);
	  }
	  delta_e = delta_e/2;
  }
  // back ward
  vec = vec - delta_e;


  float begin = 0;
  alpha_acc = begin;
  
  float elipse = 0;
  vec4 val;
  elipse = rand(vec2(length_acc,alpha_acc));
  vec += vec3(0, 0, elipse);

  for(int i = 0; i < 800; i++)
    {
      color_sample = texture3D(volumetexture,vec);
	  colorvalue = texture1D(tranf, color_sample.x);
      alpha_sample = colorvalue.a;
      col_acc   += (1.0 - alpha_acc) * colorvalue.xxxx * alpha_sample;
      alpha_acc += alpha_sample;
      vec += delta_dir;
      length_acc += delta_dir_len;
      if(length_acc >= len || alpha_acc > 1.0) break; // terminate if opacity > 1 or the ray is outside the volume
    }

 
  gl_FragColor = (alpha_acc)*col_acc + (1-alpha_acc)*vec4(0,0,0.4,1);
}
